//==============================================================================
#ifndef _GAMESERVER_H_
#define _GAMESERVER_H_

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#pragma once
#include "concurrent\Runnable.h"
#include "concurrent\ThreadPool.h"
#include "concurrent\Thread.h"
#include "concurrent\CriticalSection.h"
#include "net\ServerSocket.h"
#include "log\Log.h"
#include "SessionHandler.h"
#include "ServerReceiver.h"
#include "..\..\Persistence\persistence\GameEvent.h"
#include "Model.h"
#include <iostream>
#include <sstream>
#include <string>
#include <list>
#include <queue>

using namespace concurrent;
using namespace std;
using namespace net;
using namespace logging;

const int SERVER_MAX_PLAYER_SESSIONS = 1;

class ServerReceiver;
class SessionHandler;
class Model;

//==============================================================================
class GameServer : public Runnable
{
public:
	GameServer(string sceneName);
    GameServer(string sceneName, string port);
    virtual ~GameServer(void);

	int getNewSessionID();
	
	void setIsReady(bool flag);
	bool isReady();

	void setModel(Model* model);
	Model* getModel(void);
	
	void setReceiver(ServerReceiver* receiver);
	ServerReceiver* getReceiver();
	
	void setSocket(ServerSocket* socket);
	ServerSocket* getSocket(void);
	
	void setPort(string port);
	string getPort(void);

	list<SessionHandler*>* getSessionsLst(void);
	
	list<Thread*>* getThreadsLst(void);

	queue<GameEvent*>* getNewGameEvents();

	CriticalSection* getNewGameEventsLock(void);
	
	CriticalSection* getSessionsLstLock(void);

	CriticalSection* getPlayerSessionCountLock(void);
	void setPlayerSessionCount(int numb);
	int getPlayerSessionCount(void);
	
	bool allPlayersReady();
	
    int start(void);
	void shutdown(void);
	void addNewGameEvent(GameEvent* gameEvent);
	bool addNewPlayerSession();
	bool deletePlayerSession();
	bool addNewObserverSession();

protected:
	virtual DWORD run(void);

private:
	bool _isReady;
	bool _allPlayersReady;
	int playerSessionCount;

	CriticalSection playerSessionCountLock;

	CriticalSection newSessionIDLock;

	queue <GameEvent*> newGameEvents;
	CriticalSection newGameEventsLock;
	
	string port;
	ServerSocket* socket;

	Thread* modelThread;
	Model* model;

	Thread* receiverThread;
	ServerReceiver* receiver;
	
	list <SessionHandler*> sessionsLst;
	CriticalSection sessionsLstLock;
	
	list <Thread*> threadsLst;

	static string DEFAULT_PORT;
};

#endif
